using System.Collections;
using UnityEngine;
using UnityEngine.UI;

/*
* Introduction：    水平循环滚动视图实现，继承自LoopScrollView基类
* Version：         1.1
* Creator：         yixiang.hui
* Creation Time：   2025.9.3
*
* Last Editor：     yixiang.hui 
* Last Edit Time：  2025.9.3
* Note：            1.1版本修复了UpdateBounds方法问题，优化了水平滚动逻辑
*/

namespace Hyx.UIComponent
{
    [RequireComponent(typeof(Mask))]
    public class LoopHorizontalScrollView : LoopScrollView
    {
        private Vector2 left = Vector2.left;

        protected override float GetSize(RectTransform item)
        {
            float size = LayoutUtility.GetPreferredWidth(item) + contentSpacing;
            return size;
        }

        protected override float GetDimension(Vector2 vector)
        {
            return vector.x;
        }

        protected override Vector2 GetVector(float value)
        {
            return left * value;
        }

        protected override void Awake()
        {
            base.Awake();
            directionSign = 1;

            vertical = false;
            horizontal = true;
        }

        protected override bool UpdateItems(Bounds viewBounds, Bounds contentBounds)
        {
            bool changed = false;

            // 动态调整阈值，基于当前项目大小
            float dynamicThreshold = Mathf.Max(threshold, GetAverageItemSize() * 1.1f);

            if (viewBounds.max.x > contentBounds.max.x)
            {
                float size = NewItemAtEnd();
                if (size > 0)
                {
                    if (threshold < size)
                    {
                        threshold = size * 1.1f;
                    }
                    changed = true;
                }
            }
            else if (viewBounds.max.x < contentBounds.max.x - dynamicThreshold)
            {
                float size = DeleteItemAtEnd();
                if (size > 0)
                {
                    changed = true;
                }
            }

            if (viewBounds.min.x < contentBounds.min.x)
            {
                float size = NewItemAtStart();
                if (size > 0)
                {
                    if (threshold < size)
                    {
                        threshold = size * 1.1f;
                    }
                    changed = true;
                }
            }
            else if (viewBounds.min.x > contentBounds.min.x + dynamicThreshold)
            {
                float size = DeleteItemAtStart();
                if (size > 0)
                {
                    changed = true;
                }
            }
            return changed;
        }

        private float GetAverageItemSize()
        {
            if (content.childCount == 0) return threshold;

            float totalSize = 0;
            for (int i = 0; i < content.childCount; i++)
            {
                RectTransform item = content.GetChild(i) as RectTransform;
                totalSize += GetSize(item);
            }

            return totalSize / content.childCount;
        }

        #region scrollview 操作（增、删、改、重置、刷新、跳转、移动）
        public override void Add(int idx)
        {
            if (Application.isPlaying)
            {
                totalCount++;
                if (idx < itemTypeStart)
                    idx = itemTypeStart;

                if (idx >= itemTypeStart && idx < itemTypeEnd)
                {
                    int index = idx - itemTypeStart;
                    int si = itemTypeEnd % contentConstraintCount;

                    itemTypeEnd++;
                    RectTransform newItem = InstantiateNextItem(idx).cacheRectTransform;
                    newItem.SetSiblingIndex(index);

                    if (m_ViewBounds.min.x < m_ContentBounds.min.x + 1 && si == 0)
                    {
                        LoopViewPoolCell oldItem = GetContentChild(content.childCount - 1);
                        prefabPool.PutItem<LoopViewPoolCell>(oldItem.cacheObejct);
                        itemTypeEnd--;
                    }
                }
            }
        }

        public override void Remove(int idx)
        {
            if (idx >= totalCount)
                return;
            if (Application.isPlaying)
            {
                totalCount--;
                if (idx < itemTypeStart)
                    idx = itemTypeStart;
                if (idx >= itemTypeStart && idx < itemTypeEnd)
                {
                    int index = idx - itemTypeStart;
                    LoopViewPoolCell oldItem = GetContentChild(index);
                    prefabPool.PutItem<LoopViewPoolCell>(oldItem.cacheObejct);
                    itemTypeEnd--;
                    if (m_ViewBounds.min.x > m_ContentBounds.min.x - 1)
                    {
                        NewItemAtEnd();
                    }
                }
            }
        }

        public override void Change(int idx)
        {
            if (idx >= totalCount)
                return;
            if (Application.isPlaying)
            {
                if (idx >= itemTypeStart && idx < itemTypeEnd)
                {
                    int index = idx - itemTypeStart;
                    ItemShowHandler?.Invoke(GetContentChild(index), idx);
                }
            }
        }

        public override void Resume(int count, int startidx = 0)
        {
            totalCount = count;
            RefillCells(startidx);
        }

        public override void Refresh(int idx)
        {
            if (idx >= totalCount)
                return;
            if (idx < itemTypeStart)
                idx = itemTypeStart;
            if (idx >= itemTypeStart && idx < itemTypeEnd)
            {
                int index = idx - itemTypeStart;
                for (int i = index; i < content.childCount; i++)
                {
                    ItemShowHandler?.Invoke(GetContentChild(i), idx);
                    idx++;
                }
            }
        }

        public override void Movement(int idx)
        {
            if (Application.isPlaying)
            {
                StopMovement();
                int count = content.childCount;
                itemTypeEnd = idx + 1;
                itemTypeStart = itemTypeEnd - count;
                Canvas.ForceUpdateCanvases();

                for (int i = 0; i < count; i++)
                {
                    ItemShowHandler?.Invoke(GetContentChild(i), itemTypeStart + i);
                }

                StartCoroutine(OffsetPos());
            }
        }

        public override void DoMovement(int idx)
        {
            // 直接移动到指定索引
            if (Application.isPlaying)
            {
                StopMovement();

                if (idx < 0) idx = 0;
                if (idx >= totalCount) idx = totalCount - 1;

                // 计算目标位置
                float targetPosition = 0;
                for (int i = 0; i < idx; i++)
                {
                    // 这里需要根据实际项目大小计算位置
                    // 简化实现，实际应根据项目大小计算
                    targetPosition += 100; // 假设每个项目宽度为100
                }

                // 设置内容位置
                Vector2 pos = content.anchoredPosition;
                pos.x = -targetPosition; // 水平滚动通常是负值
                SetContentAnchoredPosition(pos);

                UpdateBounds();
            }
        }

        IEnumerator OffsetPos()
        {
            yield return null;
            int count = content.childCount;
            Vector3 rightconer = worldCorners[3];
            Transform endtrans = content.GetChild(count - 1);
            LayoutElement element = endtrans.GetComponent<LayoutElement>();
            Vector3 offsetElement = Vector3.right * element.preferredWidth * 0.5f;

            Vector3 cp = content.transform.InverseTransformPoint(endtrans.position) - offsetElement;
            Vector3 cc = content.transform.InverseTransformPoint(rightconer);
            Vector3 localOffset = cp - cc;
            if (cp.x - offsetElement.x < cc.x)
            {
                // Offset shouldn't occur if blocked
                if (!vertical) localOffset.y = 0f;
                localOffset.z = 0f;
                content.localPosition = content.transform.localPosition - localOffset;
            }
        }
        #endregion
    }
}